﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace AugustSql
{
    public class SqlInstance
    {
        internal ISqlClient sqlClient = null;

        public ISqlClient SqlClient
        {
            get { return sqlClient; }
        }

        public static ConcurrentDictionary<string, string> InquirePageNameDic = new ConcurrentDictionary<string, string>();

        private string primaryKey = string.Empty;
        public ISqlCollectionBase Register(ISqlCollectionBase sqlInformationCollection,string primaryKey ,  bool safe = true)
        {
            GC.Collect();
            this.primaryKey = primaryKey;
            sqlInformationCollection.PrimaryKey = primaryKey;
            Type registType = sqlInformationCollection.ResgistType;
            string TableName = registType.Name.ToLower();
            Attribute tbname = registType.GetCustomAttribute(typeof(TableAttribute));
            if (tbname != null)
            {
                if (tbname is TableAttribute tbatr)
                {
                    if (!string.IsNullOrEmpty(tbatr.TableName))
                        TableName = tbatr.TableName.ToLower();
                    if (!string.IsNullOrEmpty(tbatr.InquirePageListName))
                    {
                        InquirePageNameDic.TryAdd(TableName, tbatr.InquirePageListName);
                    }
                }
            }
            List<string> key = new List<string>();
            foreach (var item in registType.GetProperties())
                foreach (var ats in item.GetCustomAttributes(false))
                    if (ats is ColumAttribute colum)
                        if (colum.IsSerchKey)
                            key.Add(item.Name);
            if (key.Count <= 0)
                throw new Exception($"表 {registType.Name} 至少标记一个 Colum(IsSerchKey=true) 特性");
            string Last = primaryKey;
            if (!sqlClient.FindAllTables().Contains(TableName))
                sqlClient.ExcuteCommand(Gen(registType, primaryKey));
            else
            {
                List<string> Before = new List<string>();
                var lines = sqlClient.GetDataSet($"SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR \", \") FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '{sqlClient.database}' AND TABLE_NAME = '{TableName}';");
                if (lines.Tables.Count > 0)
                {
                    var tab = lines.Tables[0];
                    if (tab.Rows.Count > 0 || tab.Columns.Count > 0)
                    {
                        string data = tab.Rows[0][0].ToString().Replace(" ", "");
                        Before = data.Split(',').ToList();
                    }
                }
                //Before = newSQL.SqlClient.FindAllTableColums(TableName);
                var propnames = registType.GetProperties().Select(prop => prop.Name);
                foreach (var colum in propnames)
                {
                    if (!Before.Contains(colum))
                    {
                        MySqlHelper.FindColumAttribute(registType.GetProperty(colum), out var result);
                        string sql = $"ALTER TABLE `{TableName}` ADD COLUMN {result.CreatInfo().Replace(",", "")} AFTER `{Last}`;";
                        sqlClient.ExcuteCommand(sql);
                    }
                    Last = colum;
                }
                if (!safe)//需要删除多余的列数
                {
                    foreach (var oldcolum in Before)
                    {
                        if (!propnames.Contains(oldcolum))//新的表不存在旧的
                        {
                            if (oldcolum ==primaryKey)
                                continue;
                            string sql = $"ALTER TABLE `{TableName}` DROP COLUMN {oldcolum}";
                            sqlClient.ExcuteCommand(sql);
                        }
                    }
                }
            }
            Last = primaryKey;
            foreach (var item in registType.GetProperties())
            {
                MySqlHelper.FindColumAttribute(item, out var colum);
                sqlClient.ExcuteCommand($"ALTER TABLE `{TableName}` CHANGE COLUMN `{item.Name}` {colum.CreatInfo().Replace(",", "")} AFTER `{Last}`;");
                var keylist = sqlClient.GetDataSet($"show index from `{TableName}`").Tables[0].AsEnumerable().Select(c => c.Field<string>("Key_name")).ToList();
                if ((colum.IsIndexKey || colum.IsSerchKey) && !keylist.Contains(item.Name))
                    sqlClient.ExcuteCommand($"ALTER TABLE `{TableName}` ADD INDEX `{item.Name}` (`{item.Name}`);");
                else if (!colum.IsIndexKey && !colum.IsSerchKey && keylist.Contains(item.Name))
                    sqlClient.ExcuteCommand($"ALTER TABLE `{TableName}` DROP INDEX `{item.Name}`;");
                Last = item.Name;
            }
            sqlInformationCollection.SqlClient = sqlClient;
            sqlInformationCollection.TableName = TableName;
            sqlInformationCollection.Key = key.ToArray();
            var collection = sqlInformationCollection;
            return collection;
            //Dic.AddOrUpdate(typeof(T), (tp) => collection, (tp, tpold) => collection);
        }
        //internal static void CheckExist<T>() where T : SqlInformationBase
        //{
        //    if (Dic.ContainsKey(typeof(T))) return;
        //    Register<T>();
        //}

        internal static string Gen(Type type_param , string primaryKey)
        {
            TableInfor tableInfor = new TableInfor(primaryKey);
            Type type = type_param;
            var atr = type.GetCustomAttributes(false);
            tableInfor.TableName = type.Name;
            foreach (var item in atr)
            {
                if (item is TableAttribute tn)
                {
                    if (string.IsNullOrEmpty(tn.TableName))
                        tn.TableName = type.Name;
                    tableInfor.TableName = tn.TableName;
                    break;
                }
            }




            if (string.IsNullOrEmpty(tableInfor.TableName))
            {
                throw new Exception("该类必须含有TableAttribute特性");
            }
            foreach (var prop in type.GetProperties())
            {
                MySqlHelper.FindColumAttribute(prop, out var colum);
                tableInfor.AddColum(colum);
            }
            return tableInfor.CreatTable();
        }

        //public static string Gen<T>(string primaryKey) where T : SqlInformationBase
        //{
        //    return Gen(typeof(T), primaryKey);
        //}
    }
}
